﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using DataForest.ViewModel;
using DataForest.Utilities;
using System.Windows.Forms;
using DataForest.DataModel;
using System.Collections.Specialized;
using System.Diagnostics;
using DataForest.ViewModel.Dialogs;
using System.IO;

namespace DataForest.ViewModel
{
    public class MainWindowModel : BaseViewModel
    {
        public MainWindowModel(Workspace space)
        {
            workspace = space;
            workspace.WorkgroupTreeCollectionChanged += HandleTreeCollectionChanged;
            workspace.WorkgroupCollectionChanged += HandleWorkgroupCollectionChanged;
            this.Tabs = new ObservableCollection<TabModel>();
            TabModel startTab = new StartTabViewModel();
            startTab.TabCloseRequest += CloseTab;
            Tabs.Add(startTab);
            

        }

        private void HandleWorkgroupCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
        {
            if (args.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (Workgroup group in args.NewItems)
                {
                    TabModel newTab = new TableTabModel(group);
                    newTab.TabCloseRequest += CloseTab;
                    Tabs.Add(newTab);
                    SelectedTab = newTab;
                }
            }

            if (args.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (Workgroup group in args.OldItems)
                {
                    List<TabModel> oldTabs = Tabs.Where(tab => tab.Group == group).ToList();
                    foreach (TabModel tab in oldTabs)
                    {
                        tab.TabCloseRequest -= CloseTab;
                        Tabs.Remove(tab);
                    }
                }
            }
        }

        private void HandleTreeCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
        {   
            Workgroup group = sender as Workgroup;
            if (args.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (Tree tree in args.NewItems)
                {
                    TabModel newTab = new TreeTabModel(group, tree);
                    newTab.TabCloseRequest += CloseTab;
                    Tabs.Add(newTab);
                    SelectedTab = newTab;
                }
            }


            if (args.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (Tree tree in args.OldItems)
                {
                    TabModel oldTab = Tabs.FirstOrDefault(tab => tab is TreeTabModel && ((TreeTabModel)tab).Tree == tree);
                    oldTab.TabCloseRequest -= CloseTab;
                    Tabs.Remove(oldTab);
                }
            }

        }


        private TabModel selectedTab;

        private Workspace workspace;

        private RelayCommand closeCommand;
        private RelayCommand openCommand;
        private RelayCommand saveCommand;
        private RelayCommand saveAsCommand;
        private RelayCommand newtableCommand;
        private RelayCommand newtreeCommand;
        private RelayCommand createOptimalTreeCommand;
        private RelayCommand createInteractiveTreeCommand;

        public TabModel SelectedTab
        {
            get
            {
                return selectedTab;
            }
            set
            {
                if (value != selectedTab)
                {
                    selectedTab = value;
                    OnPropertyChanged("SelectedTab");
                }
            }
        }
        public ObservableCollection<TabModel> Tabs
        {
            get;
            set;
        }

        public ICommand NewTableCommand
        {
            get
            {
                if (newtableCommand == null)
                {
                    newtableCommand = new RelayCommand(param => NewTable());
                }
                return newtableCommand;
            }
        }
        public ICommand NewTreeCommand
        {
            get
            {
                if (newtreeCommand == null)
                {
                    newtreeCommand = new RelayCommand(param => NewTree());
                }
                return newtreeCommand;
            }
        }
        public ICommand OpenCommand
        {
            get
            {
                if (openCommand == null)
                {
                    openCommand = new RelayCommand(param => this.Open());
                }
                return openCommand;
            }
        }
        public ICommand CloseCommand
        {
            get
            {
                if (closeCommand == null)
                {
                    closeCommand = new RelayCommand(param => this.Close());
                }
                return closeCommand;
            }
        }
        public ICommand CreateOptimalTreeCommand
        {
            get
            {
                if (createOptimalTreeCommand == null)
                {
                    createOptimalTreeCommand = new RelayCommand(param => CreateOptimalTree(), param => (this.SelectedTab is TableTabModel || this.SelectedTab is TreeTabModel) && this.SelectedTab.Group.Table.Rows.Count > 0);
                }
                return createOptimalTreeCommand;
            }
        }
        public ICommand CreateInteractiveTreeCommand
        {
            get
            {
                if (createInteractiveTreeCommand == null)
                {
                    createInteractiveTreeCommand = new RelayCommand(param => this.CreateInteractiveTree(), param => (this.SelectedTab is TableTabModel || this.SelectedTab is TreeTabModel) && this.SelectedTab.Group.Table.Rows.Count > 0);
                }
                return createInteractiveTreeCommand;
            }

        }
        public ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new RelayCommand(param => Save());
                }
                return saveCommand;
            }
        }

        public ICommand SaveAsCommand
        {
            get
            {
                if (saveAsCommand == null)
                {
                    saveAsCommand = new RelayCommand(param => SaveAs());
                }
                return saveAsCommand;
            }
        }



        public event EventHandler RequestClose;

        private void Close()
        {
            if (RequestClose != null)
            {
                RequestClose(this, null);
            }

        }

        private void Save()
        {
            Table table = SelectedTab.Group.Table;
            if (table.FileName != null && table.FileName != "")
            {
                switch (Path.GetExtension(table.FileName).ToLower())
                {
                    
                    case ".xls":
                        ExcelDialogViewModel excelModel = new ExcelDialogViewModel();
                        excelModel.Title = "Als Excel Speichern";
                        excelModel.FirstRowColumnNames = table.WasFirstRowColumnNames;
                        if (MyDialogService.ShowDialog(excelModel) == true)
                        {
                            table.WasFirstRowColumnNames = excelModel.FirstRowColumnNames;
                            workspace.SaveExcel(SelectedTab.Group, table.FileName, excelModel.FirstRowColumnNames);
                        }
                        break;
                    case ".csv":
                    default:
                        if (table.UsedSeperatorChar == null || table.UsedSeperatorChar == "")
                        {
                            CSVDialogViewModel model = new CSVDialogViewModel();
                            model.Title = "Als .csv Speichern";
                            model.FirstRowColumnNames = table.WasFirstRowColumnNames;
                            MyDialogService.ShowDialog(model);
                            table.WasFirstRowColumnNames = model.FirstRowColumnNames;
                            table.UsedSeperatorChar = model.SeperatorChar;
                        }
                        workspace.SaveCSV(SelectedTab.Group, table.FileName, table.UsedSeperatorChar);
                        break;
                }
            }
            else
            {
                SaveAs();
                return;
            }
            
        }

        private void SaveAs()
        {
            SaveFileDialogModel dialog = new SaveFileDialogModel();
            dialog.Title = "Datei speichern";
            dialog.Filter = "Unterstützte-Dateien (*.txt,*.csv,*.xls)|*.txt; *.csv; *.xls|Zeichensepariert (*.txt,*.csv)|*.txt; *.csv|Excel-Datei (*.xls)|*.xls;";

            if (MyDialogService.ShowDialog(dialog) == true)
            {
                switch (Path.GetExtension(dialog.FileName).ToLower())
                {
                    case ".xls":
                        ExcelDialogViewModel emodel = new ExcelDialogViewModel();
                        emodel.OkayButton = "Speichern";
                        emodel.Title = "Speichern als Excel";
                        if (MyDialogService.ShowDialog(emodel) == true)
                        {
                            SelectedTab.Group.Table.FileName = dialog.FileName;
                            SelectedTab.Group.Table.WasFirstRowColumnNames = emodel.FirstRowColumnNames;
                            workspace.SaveExcel(SelectedTab.Group, SelectedTab.Group.Table.FileName, emodel.FirstRowColumnNames);
                        }
                        break;
                    case ".csv":
                    default:
                        CSVDialogViewModel model = new CSVDialogViewModel();
                        model.OkayButton = "Speichern";
                        model.Title = "Speichern als .csv";
                        if (MyDialogService.ShowDialog(model) == true)
                        {
                            SelectedTab.Group.Table.FileName = dialog.FileName;
                            SelectedTab.Group.Table.UsedSeperatorChar = model.SeperatorChar;
                            SelectedTab.Group.Table.WasFirstRowColumnNames = model.FirstRowColumnNames;
                            workspace.SaveCSV(SelectedTab.Group, SelectedTab.Group.Table.FileName, SelectedTab.Group.Table.UsedSeperatorChar);
                        }
                        break;

                }
            }
        }

        private void Open()
        {

            OpenFileDialogModel dialog = new OpenFileDialogModel();
            dialog.Title = "Datei öffnen";
            dialog.Filter = "Unterstützte-Dateien (*.txt,*.csv,*.xls,*.xml)|*.txt; *.csv; *.xls; *.xml|Zeichensepariert (*.txt,*.csv)|*.txt; *.csv|Excel-Datei (*.xls)|*.xls;|Xml-Datei (*.xml)|*.xml";

            if (MyDialogService.ShowDialog(dialog) == true)
            {
                try
                {
                    switch (Path.GetExtension(dialog.FileName).ToLower())
                    {
                        case ".csv":
                        
                                CSVDialogViewModel model = new CSVDialogViewModel();
                                model.OkayButton = "Öffnen";
                                model.Title = "Öffnen als .csv";
                                if (MyDialogService.ShowDialog(model) == true)
                                {
                                    Workgroup group = workspace.LoadCSV(dialog.FileName, model.SeperatorChar);
                                }
                        
                            break;
                        case ".xls":
                            ExcelDialogViewModel excelModel = new ExcelDialogViewModel();
                            excelModel.OkayButton = "Öffnen";
                            excelModel.Title = "Öffnen als Excel";
                            if (MyDialogService.ShowDialog(excelModel) == true)
                            {
                                Workgroup group = workspace.LoadExcel(dialog.FileName, excelModel.ExcelTable, excelModel.FirstRowColumnNames);
                            }
                            break;
                        case ".xml":
                            break;

                    }
                }
                catch (Exception ex)
                {
                    ErrorMessageDialogModel error = new ErrorMessageDialogModel();
                    error.Message = "Beim Öffnen der Datei trat ein Fehler auf: \n" + ex.Message;
                    error.Title = "Fehler!";
                    MyDialogService.ShowDialog(error);
                }

            }
            
        }

        private void NewTable()
        {
            workspace.AddWorkgroup();
        }


        private void NewTree()
        {
            if (SelectedTab != null) {
                workspace.AddInteractiveTree(SelectedTab.Group);
            }
            /*var tab = new TreeTabModel ("Neuer Baum"){ };
            Tabs.Add(tab);
            tab.TabCloseRequest += CloseTab;
            SelectedTab = tab;*/
        }

        private void CloseTab(object sender, EventArgs e)
        {
            if (sender is TreeTabModel)
            {
                TreeTabModel tree = sender as TreeTabModel;
                workspace.RemoveTree(tree.Group, tree.Tree);
            }
            else if (sender is TableTabModel)
            {
                TableTabModel table = sender as TableTabModel;
                workspace.RemoveWorkgroup(table.Group);
            }
            else
            {
                Tabs.Remove(sender as TabModel);
            }
        }

        private void CreateOptimalTree()
        {
            if (SelectedTab != null)
            {
                workspace.AddOptimalTree(SelectedTab.Group);
            }
        }

        private void CreateInteractiveTree()
        {

            if (SelectedTab != null)
            {
                workspace.AddInteractiveTree(SelectedTab.Group);
            }
        }


    }
}



